home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
HPAVC
/
HPAVC CD-ROM.iso
/
PRUS101.ZIP
/
FCHARS.ASM
< prev
next >
Wrap
Assembly Source File
|
1994-12-19
|
14KB
|
442 lines
TITLE FChars - Code fuer Turbo-Pascal-Funktionen zur
SUBTTL Bearbeitung von NUL-terminierten Strings im C-Format
; goes along with FIDO unit to add Borland Pascal 7.0's Strings functions to
; prior versions
; ***************************************************************************
; RELEASE 1.0 - as first contained in the file PRUS101.LZH
; by Sieghard Schicktanz, 2:2480/642.25, GERMANY
; --------------------------------------------
; organized for Fido's PASCAL related echoes
; --------------------------------------------
; 08/02/1994 to --/--/---- by Sieghard Schicktanz, 2:2480/642.25, GERMANY
; As far as third party copyrights are not violated this
; source code is hereby placed to the public domain. Use
; it whatever way you want, but use AT YOUR OWN RISK.
; In case you should modify the source rather send your
; modifications to the unit's current organizer (see above for
; NM address) than to spread it on your own. This will help to
; keep the unit updated and grant a certain standard to all
; other users as well.
; The unit is currently still under work. So it might greatly
; benefit of your participation.
; Those who contributed to the following piece of source,
; listed in alphabethical order:
; ================================================================
; Andrew Eigus, Sieghard Schicktanz, ...
; ================================================================
; YOUR NAME WILL APPEAR HERE IF YOU CONTRIBUTE USEFUL SOURCE.
; Credits in your own programs are as welcome as unnecessary.
; ***************************************************************************
.MODEL TPASCAL
PUBLIC Str2PChar, StrCat, StrComp, StrCopy, StrECopy
PUBlIC StrEnd, StrLCat, StrLComp, StrLCopy
PUBlIC StrLen, StrPas, StrRScan, StrScan, StrSkip
; %StrPCopy% implemented differently!
; First, let's declare a couple of abbreviations and macros
; that should make the code more readable
pntr EQU DWORD ; this relates to the standard Pascal pointer type
Rseg EQU DX ; return registers used for
Roff EQU AX ; pointer values and
Rint EQU AX ; integer values by Turbo Pascal
SetUp MACRO Regs ; this will be used to set up segment registers
LOCAL @reg
CLD
IRP @reg, <Regs>
PUSH @reg
ENDM
ENDM
CleanUp MACRO Regs ; this restores segments and returns cleanly
LOCAL @reg
IRP @reg, <Regs>
POP @reg
ENDM
RET
ENDM
LOCALS @@ ; tell the assembler how locals are marked
; Now to the real thing - function code starts below
.CODE ; use this bloody segment
Str2PChar PROC FAR source: pntr
; FUNCTION Str2PChar (str: string): PChar;
SetUp <DS, ES>
CLD
LES DI, source ; this is done in place!
LDS SI, source ; so target is same as source
SUB CX, CX
LODSB ; get count byte
MOV CL, AL
JCXZ @@nix ; nothing to do?
REP MOVSB ; move string down a notch
SUB AL, AL ; and stick the NUL terminator
@@nix:
STOSB ; to the end
LES DI, source ; now return
MOV Rseg, ES ; input address
MOV Roff, DI ; as output
CleanUp <ES, DS>
Str2PChar ENDP
StrCat PROC FAR dest: pntr, source: pntr
; FUNCTION StrCat (dest, source: PChar): PChar;
SetUp <DS, ES>
CLD
LES DI, dest
TEST BYTE PTR ES:[DI], -1 ; see if anything to do
JZ @@nix ; no, is empty
SUB AL, AL ; scan for NUL
SUB CX, CX ; as much as 64 KB
REPNZ SCASB
@@nix:
JMP copy_string ; copy other one behind
StrCat ENDP
StrComp PROC FAR dest: pntr, source: pntr
; FUNCTION StrComp (dest, source: PChar): integer;
SetUp <DS, ES>
CLD
LDS SI, source
LES DI, dest
@@next:
LODSB ; get current source char
SCASB ; compare with target char
JA @@more ; not equal?
JB @@less ; what's the difference?
OR AL, AL ; hit terminator?
JNZ @@next ; not yet, continue
@@null:
SUB Rint, Rint ; all compared ok
@@done:
CleanUp <ES, DS>
@@less:
MOV Rint, -1 ; dest was "greater"
JMP SHORT @@done
@@more:
MOV Rint, 1 ; dest was "less"
JMP SHORT @@done
StrComp ENDP
StrCopy PROC FAR dest: pntr, source: pntr
; FUNCTION StrCopy (dest, source: PChar): PChar;
SetUp <DS, ES>
CLD
LES DI, dest
copy_string: ; an entry from elsewhere...
LDS SI, source ; (see below)
@@next:
LODSB ; copy characters
STOSB
OR AL, AL ; till NUL terminator
JNZ @@next
LES DI, dest
MOV Rseg, ES
MOV Roff, DI
CleanUp <ES, DS>
StrCopy ENDP
StrECopy PROC FAR dest: pntr, source: pntr
; FUNCTION StrECopy (dest, source: PChar): PChar;
SetUp <DS, ES>
LDS SI, source
LES DI, dest
CLD
@@next:
LODSB ; copy characters
STOSB
OR AL, AL ; till NUL terminator
JNZ @@next
DEC DI ; went one too far
MOV Rseg, ES ; set up return registers
MOV Roff, DI ; for pointer value
CleanUp <ES, DS>
StrECopy ENDP
StrEnd PROC FAR source: pntr
; FUNCTION StrEnd (source: PChar): PChar;
SetUp ES
CLD
MOV CX, -1
LES DI, source
SUB AL, AL ; look out for NUL
REPNZ SCASB
DEC DI ; was just behind
MOV Rseg, ES ; and return pointer to
MOV Roff, DI ; terminator
CleanUp ES
StrEnd ENDP
StrLCat PROC FAR dest: pntr, source: pntr, n: WORD
; FUNCTION StrLCat (dest, source: PChar; n: byte): PChar;
SetUp <DS, ES>
CLD
LES DI, dest
TEST BYTE PTR ES:[DI], -1 ; see if anything to do
JZ @@nix ; no, is empty
SUB AL, AL ; scan for NUL
SUB CX, CX ; as much as 64 KB
REPNZ SCASB
@@nix:
JMP copy_n_chars ; copy other one behind
StrLCat ENDP
StrLComp PROC FAR dest: pntr, source: pntr, n: WORD
; FUNCTION StrLComp (dest, source: PChar; n: byte): integer;
SetUp <DS, ES>
MOV CX, n ; get compare count
JCXZ @@null ; nothing to do?
LDS SI, source
LES DI, dest
CLD
@@next:
LODSB ; get current source char
SCASB ; compare with target char
JA @@more ; not equal?
JB @@less ; what's the difference?
OR AL, AL ; hit terminator?
LOOPNZ @@next ; not yet, continue
@@null:
SUB Rint, Rint ; all compared ok
@@done:
CleanUp <ES, DS>
@@less:
MOV Rint, -1 ; dest was "greater"
JMP SHORT @@done
@@more:
MOV Rint, 1 ; dest was "less"
JMP SHORT @@done
StrLComp ENDP
StrLCopy PROC FAR dest: pntr, source: pntr, n: WORD
SetUp <DS, ES>
CLD
LES DI, dest
copy_n_chars:
MOV CX, n
JCXZ @@nix
LDS SI, source
REP MOVSB
@@nix:
SUB AL, AL
STOSB
LES DI, dest ; reset to beginning
MOV Rseg, ES ; to be passed
MOV Roff, DI ; back
CleanUp <ES, DS>
StrLCopy ENDP
StrLen PROC FAR source: pntr
; FUNCTION StrLen (source: PChar): word;
SetUp ES ; not _really_ needed...
SUB CX, CX ; assume empty
LES DI, source ; now get the address
TEST BYTE PTR ES:[DI], -1 ; and test the first char
JZ @@nix ; really empty!
CLD ; _always_ go upstairs!
DEC CX
SUB AL, AL ; scan for NUL byte
REPNZ SCASB ; within string
INC CX ; convert counter register
NOT CX ; to distance from start
@@nix:
MOV Rint, CX ; and return in result reg
CleanUp ES
StrLen ENDP
StrPas PROC FAR cstring: pntr RETURNS pstring: pntr
; FUNCTION StrPas (source: PChar): string;
SetUp <DS, ES>
LDS SI, cstring ; this is the source
MOV AX, DS
OR AX, SI ; check for NIL
JZ @@thru ; if so we're done
LES DI, pstring ; the target is implicitely
CLD ; passed by the compiler!
SUB AX, AX ; clear length counter
STOSB ; skip length byte
@@next:
LODSB ; now check this char
OR AL, AL ; hit NUL terminator?
JZ @@thru ; then we're done
INC AH ; else increment counter
JZ @@over
STOSB ; and copy this one over
JMP @@next ; continue
@@over:
DEC AH ; don't count terminator
@@thru:
MOV AL, AH ; put count into correct register
LES DI, pstring ; point at start of result
STOSB ; and put count there
CleanUp <ES, DS>
StrPas ENDP
COMMENT %
StrPCopy PROC FAR dest: pntr, source: pntr
; FUNCTION StrPCopy (dest: PChar; source: string): PChar;
SetUp <DS, ES>
LES DI, dest
LDS SI, source
SUB CX, CX
LODSB
MOV CL, AL
JCXZ @@nix
CLD
REP MOVSB
SUB AL, AL
@@nix:
STOSB
LES DI, dest
MOV Rseg, ES
MOV Roff, DI
CleanUp <ES, DS>
StrPCopy ENDP
%
StrScan PROC FAR source: pntr, chr: WORD
; FUNCTION StrScan (source: PChar; ch: char): PChar;
SetUp DS
CLD
LDS SI, source
MOV DX, chr
@@next:
LODSB
OR AL, AL ; see if at end already
JZ @@null ; yes, hit terminator
CMP AL, DL ; is it requested char?
JNZ @@next ; no, get next one
@@found:
MOV Rseg, DS ; return pointer
MOV Roff, SI ; to target char
DEC Roff ; went one too far
CleanUp DS
@@null:
SUB Rseg, Rseg ; else return NIL
MOV Roff, Rseg
CleanUp DS
StrScan ENDP
StrRScan PROC FAR source: pntr, chr: WORD
; FUNCTION StrRScan (source: PChar; ch: char): PChar;
SetUp ES
LES DI, source ; now get the address
TEST BYTE PTR ES:[DI], -1 ; and test the first char
JZ @@null ; cannot be!
CLD
MOV CX, -1
SUB AL, AL ; find terminating NUL
REPNZ SCASB
DEC DI ; revert to terminator
NOT CX ; to real string length
MOV AX, chr ; get what to search for
STD ; do it backwards now!
REPNZ SCASB ; and off we go!
JNZ @@null ; nope, not found
@@found:
MOV Rseg, ES ; return pointer
MOV Roff, DI ; to target char
INC Roff ; went one too far
CLD ; just for safety
CleanUp ES
@@null:
SUB Rseg, Rseg ; else return NIL
MOV Roff, Rseg
CleanUp ES
StrRScan ENDP
StrSkip PROC FAR source: pntr
; FUNCTION StrSkip (source: PChar): PChar;
SetUp ES
MOV CX, -1
LES DI, source
SUB AL, AL ; look out for NUL
CLD
REPNZ SCASB
MOV Rseg, ES ; and return pointer to
MOV Roff, DI ; just behind
CleanUp ES
StrSkip ENDP
END